<template>
	<div class="upload-file">
		<Upload
			v-if="!detailed"
			ref="upload"
			action="#"
			:file-list="fileList"
			:limit="limit"
			:http-request="httpRequest"
			:before-upload="beforeUpload"
			:on-exceed="handleExceed"
			:show-file-list="false"
			v-bind="$attrs"
			v-on="$listeners"
		>
			<slot name="trigger">
				<Button size="small">{{buttonText}}</Button>
			</slot>
			<slot name="tip"/>
			<slot/>
		</Upload>
		<div class="custom-file-list">
			<transition-group
				name="list"
				tag="div"
			>
				<div
					v-for="file in fileList"
					:key="file.fileId"
					class="custom-file-item"
				>
					<span> <i class="el-icon-paperclip"/> {{file.name}} ({{formatFileSize(file.size)}})</span>
					<div>
						<Button
							type="text"
							icon="el-icon-view"
							class="custom-file-icon"
							@click="handlePreview(file)"
						/>
						<Button
							type="text"
							icon="el-icon-download"
							class="custom-file-icon"
							@click="handleDownload(file)"
						/>
						<Button
							v-if="!detailed"
							type="text"
							icon="el-icon-close"
							class="custom-file-icon"
							@click="handleRemove(file)"
						/>
					</div>
				</div>
			</transition-group>
		</div>
		<ImageViewer
			v-if="showViewer"
			:z-index="9998"
			:url-list="[previewUrl]"
			:on-close="closeViewer"
		/>
		<Drawer
			:visible.sync="dialogVisible"
			:modal="false"
			direction="ttb"
		>
			<template #title>
				<span class="drawer-title">附件预览</span>
			</template>
			<iframe
				:src="previewUrl"
				width="100%"
				height="100%"
			/>
		</Drawer>
	</div>
</template>

<script>
import {magic} from '@lexmis/magic-ui/pc';
import ImageViewer from 'element-ui/packages/image/src/image-viewer.vue';
// import * as XLSX from 'xlsx';
import mammoth from 'mammoth';
import {Upload, Button, Drawer} from 'element-ui';
const units = {
	KB:1024,
	MB:1024 * 1024,
	GB:1024 * 1024 * 1024,
};
export default {
	name:'McUploadFile',
	components:{ImageViewer, Upload, Button, Drawer},
	props:{
		detailed:{
			type:Boolean,
			default:false,
		},
		disabled:{
			type:Boolean,
			default:false,
		},
		buttonText:{
			type:String,
			default:'选择文件',
		},
		value:{
			type:[String, Array],
		},
		detailFileList:{
			type:Array,
			default: () => [],
		},
		accept:{
			type:String,
			default:'*',
		},
		limit:{
			type:Number,
			default:0,
		},
		sizeUnit:{
			type:String,
			default:'MB',
		},
		fileSize:{
			type:Number,
			default:5,
		},
	},
	data(){
		return {
			showViewer:false,
			dialogVisible:false,
			fileList:[],
			previewUrl:[''],
		};
	},
	mounted(){
		const isArrayValue = Array.isArray(this.value);
		const hasValue = isArrayValue ? this.value?.length > 0 : !!this.value;
		if(!hasValue){
			return;
		}
		if(this.detailed){
			this.fileList = this.detailFileList || [];
			return;
		}
		const idList = isArrayValue ? this.value : [this.value];

		magic.core
			.service({
				url:'/api/magic-file/getFileRelation',
				method:'post',
				data:{idList},
			})
			.then(({data}) => {
				this.fileList = (data || []).map((item) => ({
					fileId:item.fileId,
					url:item.previewUrl,
					name:item.fileName,
				}));
			})
			.catch(() => {
				this.fileList = [];
			});
	},
	methods:{
		handlePreview({name, fileId}){
			const validExtensions = /\.(png|jpg|jpeg|gif)$/i;
			const isPicture = validExtensions.test(name);
			if(isPicture){
				this.showViewer = true;
			}else{
				this.dialogVisible = true;
			}
			// this.previewUrl = `/api/magic-file/download?id=${fileId}`;
			//TODO 待预览服务开发完成调试
			window.open(
				`/api/magic-file/download?id=${fileId}`,
				'_self',
			);
		},
		handleDownload({fileId}){
			window.open(
				`/api/magic-file/download?id=${fileId}`,
				'_self',
			);
		},
		closeViewer(){
			this.showViewer = false;
		},
		httpRequest({file}){
			magic.core.uploadFile(file).then(async (res) => {
				try{
					const iframeSrc = await this.generateFileUrl(file);
					this.fileList.push({
						name:file.name,
						url:iframeSrc,
						size:file.size,
						fileId:res.fileId,
					});
					if(this.limit > 1){
						const ids = this.fileList.map((item) => item.fileId);
						this.$emit('input', ids);
						this.$emit('change', ids);
					}else{
						const id = this.fileList[0].fileId;
						this.$emit('input', id);
						this.$emit('change', id);
					}
				}catch(error){
					console.error('处理文件上传时出错:', error);
				}
			});
		},
		async generateFileUrl(file){
			const extension = this.getFileExtension(file.name);
			if(extension === 'xls' || extension === 'xlsx'){
				// return this.getXlsUrl(file);
			}else if(extension === 'pdf'){
				return this.getPdfUrl(file);
			}else if(extension === 'doc' || extension === 'docx'){
				return this.getWordUrl(file);
			}else{
				return URL.createObjectURL(file);
			}
		},
		getFileExtension(filename){
			const match = filename.match(/\.(\w+)$/);
			return match ? match[1].toLowerCase() : '';
		},
		getWordUrl(file){
			return this.readFile(file, async (arrayBuffer) => {
				const {value} = await mammoth.convertToHtml({arrayBuffer});
				const htmlContent = `
				<style>
					body { font-family: Arial, sans-serif; }
					p { margin: 10px 0; }
				</style>
				<div>${value}</div>`;
				return this.createBlobUrl(htmlContent, 'text/html');
			});
		},
		// getXlsUrl(file){
		// 	return this.readFile(file, (data) => {
		// 		const workbook = XLSX.read(new Uint8Array(data), {type:'array'});
		// 		let htmlString = `
		// 			<style>
		// 				table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
		// 				th, td { border: 1px solid black; padding: 8px; text-align: left; }
		// 				h2 { margin: 20px 0 10px; }
		// 			</style>`;
		// 		workbook.SheetNames.forEach((sheetName) => {
		// 			try{
		// 				const sheet = workbook.Sheets[sheetName];
		// 				htmlString += `<h2>${sheetName}</h2>${XLSX.utils.sheet_to_html(sheet)}`;
		// 			}catch(error){
		// 				console.error(`Error processing sheet ${sheetName}:`, error);
		// 			}
		// 		});
		// 		return this.createBlobUrl(htmlString, 'text/html');
		// 	});
		// },
		getPdfUrl(file){
			return this.readFile(file, (data) =>
				this.createBlobUrl(data, 'application/pdf'));
		},
		readFile(file, onLoad){
			return new Promise((resolve, reject) => {
				if(!file) return reject('No file provided');
				const reader = new FileReader();
				reader.onload = (e) => resolve(onLoad(e.target.result));
				reader.onerror = (e) => reject(`File read error: ${e.message}`);
				reader.readAsArrayBuffer(file);
			});
		},
		createBlobUrl(data, type){
			const blob = new Blob([data], {type});
			return URL.createObjectURL(blob);
		},
		acceptText(){
			let txt = '';
			if(this.accept.includes('image/*')){
				txt += '、图片';
			}
			if(this.accept.includes('video/*')){
				txt += '、视频';
			}
			if(this.accept.includes('audio/*')){
				txt += '、音频';
			}
			if(this.accept.includes('.xls,.xlsx')){
				txt += '、excel';
			}
			if(this.accept.includes('.doc,.docx')){
				txt += '、word';
			}
			if(this.accept.includes('.pdf')){
				txt += '、pdf';
			}
			if(this.accept.includes('.txt')){
				txt += '、txt';
			}
			return txt.slice(1);
		},
		handleExceed(){
			this.$message.error(`当前限制最多可以上传${this.limit}个文件`);
		},
		beforeUpload(file){
			const unitNum = units[this.sizeUnit];
			const isRightSize = this.fileSize ? file.size / unitNum < this.fileSize : true;
			if(!isRightSize){
				this.$message.error(`文件大小超过${this.fileSize}${this.sizeUnit}`);
				return isRightSize;
			}
			let isAccept = false;
			if(!this.accept){
				isAccept = true;
			}
			const extension = file.name.split('.').pop().toLowerCase();
			if(this.accept.indexOf(extension) > -1){
				isAccept = true;
			}else if(this.accept === '*'){
				isAccept = true;
			}else{
				let isImage = false;
				let isVideo = false;
				let isAudio = false;
				if(this.accept.includes('image/*')){
					const type = file.fileType;
					isImage = new RegExp('image/*').test(type);
					if(isImage){
						isAccept = true;
					}else{
						if(this.accept.includes('video/*')){
							isVideo = new RegExp('video/*').test(type);
							if(isVideo){
								isAccept = true;
							}else{
								if(this.accept.includes('audio/*')){
									isAudio = new RegExp('audio/*').test(type);
									if(isAudio){
										isAccept = true;
									}
								}
							}
						}else{
							if(this.accept.includes('audio/*')){
								isAudio = new RegExp('audio/*').test(type);
								if(isAudio){
									isAccept = true;
								}
							}
						}
					}
				}else if(this.accept.includes('video/*')){
					const type = file.fileType;
					isVideo = new RegExp('video/*').test(type);
					if(isVideo){
						isAccept = true;
					}else{
						if(this.accept.includes('audio/*')){
							isAudio = new RegExp('audio/*').test(type);
							if(isAudio){
								isAccept = true;
							}
						}
					}
				}else if(this.accept.includes('audio/*')){
					const type = file.fileType;
					isAudio = new RegExp('audio/*').test(type);
					if(isAudio){
						isAccept = true;
					}
				}
			}
			if(!isAccept){
				this.$message.error(`请选择${this.acceptText()}类型的文件`);
				return isAccept;
			}
			return true;
		},
		handleRemove(file){
			this.fileList = this.fileList.filter((item) => item.fileId !== file.fileId);
			if(this.limit > 1){
				const ids = this.fileList.map((item) => item.fileId);
				this.$emit('input', ids);
				this.$emit('change', ids);
			}else{
				const id = this.fileList[0].fileId;
				this.$emit('input', id);
				this.$emit('change', id);
			}
		},
		formatFileSize(size){
			if(size < 1024) return `${size} B`;
			const kbSize = size / 1024;
			if(kbSize < 1024) return `${kbSize.toFixed(2)} KB`;
			const mbSize = kbSize / 1024;
			if(mbSize < 1024) return `${mbSize.toFixed(2)} MB`;
			const gbSize = mbSize / 1024;
			if(gbSize < 1024) return `${gbSize.toFixed(2)} GB`;
			const tbSize = gbSize / 1024;
			return `${tbSize.toFixed(2)} TB`;
		},
	},
};
</script>

<style lang="scss" scoped>
.custom-file-item {
  display: flex;
  justify-content: space-between;
}
.custom-file-icon{
	font-size: 14px;
}
.drawer-title{
	font-weight: bold;
	font-size: 18px;
}
.list-enter-active, .list-leave-active {
  transition: all 1s;
}
.list-enter, .list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
.upload-file{
	::v-deep(.Drawer) {
		height: 100% !important;
	}
}
</style>